package com.huqing.icu.service.app.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huqing.icu.base.PagingDto;
import com.huqing.icu.base.redis.annotation.RedisLock;
import com.huqing.icu.constants.CacheLockConstants;
import com.huqing.icu.dto.CommentDto;
import com.huqing.icu.dto.CommentQueryDto;
import com.huqing.icu.enums.BusinessConstants;
import com.huqing.icu.exceptions.BusinessException;
import com.huqing.icu.inout.in.CommentAddReq;
import com.huqing.icu.inout.in.CommentListQueryReq;
import com.huqing.icu.inout.in.CommentReplyReq;
import com.huqing.icu.inout.out.CommentListQueryResp;
import com.huqing.icu.mapper.CommentMapper;
import com.huqing.icu.mapper.UserCommentLikeMapper;
import com.huqing.icu.model.Comment;
import com.huqing.icu.service.CommentService;
import com.huqing.icu.service.UserCommentLikeService;
import com.huqing.icu.utils.CopyUtils;
import com.huqing.icu.utils.PageUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 评论接口
 *
 * @author huqing
 * @date 2024-12-14 15:28
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    @Resource
    private CommentMapper commentMapper;
    @Resource
    private UserCommentLikeMapper userCommentLikeMapper;
    @Autowired
    private UserCommentLikeService userCommentLikeService;

    /**
     * 新增一级评论
     *
     * @param addReq
     * @return
     */
    @RedisLock(key = CacheLockConstants.CommentPrefix.ADD_COMMENT, waitTime = 3000)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer addComment(CommentAddReq addReq) {

        //1、 查询对应的业务是否存在

        //2 检查回复的内容和图片是否满足合法

        //3 查询调用用户信息模块查询用户信息

        //4 既然合法，就保存到数据库
        Comment comment = new Comment();
        comment.setUserId(addReq.getUserId());
        comment.setBusType(addReq.getBusType());
        comment.setBusId(addReq.getBusId());
        comment.setUserNickname("");
        comment.setUserAvatar("");
        comment.setContent(addReq.getContent());
        comment.setImages(addReq.getImages());
        save(comment);
        return 1;
    }

    /**
     * 回复评论
     *
     * @param replyReq
     * @return
     */
    @RedisLock(key = CacheLockConstants.CommentPrefix.REPLY_COMMENT, waitTime = 3000)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer replyComment(CommentReplyReq replyReq) {
        //1、查询这个业务下的这个父评论是否存在，存在则说明，不能直接根据id来查，因为得判断这个父评论是不是这个业务下的
        Comment parentComment = lambdaQuery().eq(Comment::getId, replyReq.getReplyId()).eq(Comment::getBusType, replyReq.getBusType()).eq(Comment::getBusId, replyReq.getBusId()).one();
        if (parentComment == null) {
            throw new BusinessException(BusinessConstants.DATA_NOT_EXIST.getCode(), "回复的评论不存在，请检查");
        }

        //2 检查回复的内容和图片是否满足合法

        //3 查询调用用户信息模块查询用户信息

        //4 既然合法，就保存到数据库
        Comment replay = new Comment();
        replay.setUserId(replyReq.getUserId());
        replay.setBusType(replyReq.getBusType());
        replay.setBusId(replyReq.getBusId());
        replay.setUserNickname("");
        replay.setUserAvatar("");
        replay.setContent(replyReq.getContent());
        replay.setImages(replyReq.getImages());
        replay.setReplyId(replyReq.getReplyId());
        Long topCommentId = parentComment.getTopCommentId() == null ? parentComment.getId() : parentComment.getTopCommentId();
        replay.setTopCommentId(topCommentId);
        save(replay);

        //第一个评论的回复数+1
        commentMapper.incrReplyNum(topCommentId);
        return 1;
    }

    /**
     * 删除评论，只能删除自己的评论
     *
     * @param id
     * @param userId
     * @return
     */
    @RedisLock(key = CacheLockConstants.CommentPrefix.DELETE_COMMENT, waitTime = 3000)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer deleteComment(Long id, Long userId) {

        //1 根据id和userId查询这个评论是否存在
        Comment comment = lambdaQuery().eq(Comment::getId, id).eq(Comment::getUserId, userId).one();
        if (comment == null) {
            throw new BusinessException(BusinessConstants.DATA_NOT_EXIST.getCode(), "评论不存在，请检查");
        }

        //2 删除评论，逻辑删除
        int res = commentMapper.deleteById(id);
        return 1;
    }

    /**
     * 给评论点赞或取消点赞
     *
     * @param id
     * @param userId
     * @return
     */
    @RedisLock(key = CacheLockConstants.CommentPrefix.LIKE_COMMENT, waitTime = 3000)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer likeComment(Long id, Long userId) {
        //1 根据id查询这个评论是否存在
        Comment comment = lambdaQuery().eq(Comment::getId, id).one();
        if (comment == null) {
            throw new BusinessException(BusinessConstants.DATA_NOT_EXIST.getCode(), "评论不存在，请检查");
        }

        //2 新增或删除点赞行为，并给点赞数 +1 或者 -1
        userCommentLikeService.likeComment(id, userId);

        return 1;
    }

    /**
     * 查询评论列表
     *
     * @param queryReq
     * @return
     */
    @Override
    public PagingDto<CommentListQueryResp> queryCommentList(CommentListQueryReq queryReq) {
        CommentQueryDto commentQueryDto = CopyUtils.copy(queryReq, CommentQueryDto.class);
        int startIndex = PageUtils.getPageStartIndex(queryReq.getPageIndex(), queryReq.getPageSize());
        commentQueryDto.setStartIndex(startIndex);
        commentQueryDto.setFloor(1);

        //2、查询满足条件有多少个
        Integer count = commentMapper.getNumByCondition(commentQueryDto);
        if (count == 0) {
            return new PagingDto(Collections.emptyList(), 0, 0);
        }

        //查询一级评论
        List<CommentDto> topCommentDtoList = commentMapper.selectByCondition(commentQueryDto);
        List<Long> topCommentIdList = topCommentDtoList.stream().map(CommentDto::getId).collect(Collectors.toList());

        //查询这些一级评论下的子评论
        CommentQueryDto subQueryDto = new CommentQueryDto();
        subQueryDto.setBusType(commentQueryDto.getBusType());
        subQueryDto.setBusId(commentQueryDto.getBusId());
        subQueryDto.setTopCommentIdList(topCommentIdList);
        List<CommentDto> subCommentList = commentMapper.selectByCondition(commentQueryDto);
        Map<Long, List<CommentDto>> subCommentListMap = null;
        if (CollectionUtils.isNotEmpty(subCommentList)) {
            setReplyUser(subCommentList);
            subCommentListMap = subCommentList.stream().collect(Collectors.groupingBy(CommentDto::getTopCommentId));
        }

        //查询这个业务的的作者
        Long authorId = null;

        //判断评论是不是作者本人的
        judgeIsAuthor(topCommentDtoList, authorId);

        //遍历每个一级评论
        List<CommentListQueryResp> commentListResps = CopyUtils.copyOriginListToDestList(topCommentDtoList, CommentListQueryResp.class);
        for (CommentListQueryResp topComment : commentListResps) {

            //给每个一级评论赋值子评论
            if (subCommentListMap != null && subCommentListMap.containsKey(topComment.getId())) {
                subCommentList = subCommentListMap.get(topComment);
                //判断子评论是不是作者本人
                judgeIsAuthor(subCommentList, authorId);
                List<CommentListQueryResp> subcommentResps = CopyUtils.copyOriginListToDestList(subCommentList, CommentListQueryResp.class);
                topComment.setSubCommentList(subcommentResps);
            }
        }

        PagingDto pagingDto = new PagingDto<>(commentListResps, PageUtils.getTotalPage(count, queryReq.getPageSize()), count);
        return pagingDto;
    }

    /**
     * 给每个评论设置父级评论的用户昵称
     *
     * @param subCommentList
     */
    private void setReplyUser(List<CommentDto> subCommentList) {
        if (CollectionUtils.isEmpty(subCommentList)) {
            return;
        }
        Map<Long, CommentDto> subCommentMap = subCommentList.stream().collect(Collectors.toMap(CommentDto::getId, p -> p));
        for (CommentDto subComment : subCommentList) {

            //设置父级评论的用户昵称
            if (subCommentMap.containsKey(subComment.getReplyId())) {
                CommentDto parentComment = subCommentMap.get(subComment.getReplyId());
                subComment.setReplyUserNickname(parentComment.getUserNickname());
            }
        }
    }

    /**
     * 判断评论人是不是作者本人
     *
     * @param commentDtoList
     * @param authorId
     */
    private void judgeIsAuthor(List<CommentDto> commentDtoList, Long authorId) {
        if (CollectionUtils.isEmpty(commentDtoList)) {
            return;
        }
        for (CommentDto commentDto : commentDtoList) {
            if (commentDto.getUserId().equals(authorId)) {
                commentDto.setIsAuthor(1);
            }
        }
    }

    /**
     * 判断评论人是不是我的
     *
     * @param commentDtoList
     * @param authorId       作者ID
     * @param currentUserId  当前用户ID
     */
    private void judgeIsMy(List<CommentDto> commentDtoList, Long authorId, Long currentUserId) {
        if (CollectionUtils.isEmpty(commentDtoList)) {
            return;
        }
        //如果当前登录人就是作者，说明是作者本人在浏览，则展示“我的”
        if (currentUserId.equals(authorId)) {
            commentDtoList.stream().forEach(o -> o.setIsMy(1));
        } else {
            //如果当前登录人不是评论的作者，则需要看看哪些评论是当前登录人的，是的话则展示“我的”
            commentDtoList.stream().forEach(o -> {
                if (o.getUserId().equals(currentUserId)) {
                    o.setIsMy(1);
                }
            });
        }
    }
}
